package com.linsir.gen.util;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.linsir.core.config.BaseConfig;
import com.linsir.core.mapper.JaxbMapper;
import com.linsir.core.util.D;
import com.linsir.core.util.FileUtils;
import com.linsir.core.util.S;
import com.linsir.gen.dto.SysGenTableDTO;
import com.linsir.gen.entity.*;
import jakarta.xml.bind.JAXBException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;

import java.io.*;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * @author ：linsir
 * @date ：Created in 2022/10/8 11:35
 * @description：生成代码工具
 * @modified By：
 * @version:
 */
@Slf4j
public class GenUtils {

    public GenUtils()
    {
    }

    /***
    * @Description: 初始化
    * @Param: [genTable, dictList]
    * @return: void
    * @Author: linsir
    * @Date: 2022/10/10 10:18
    */
    public static void initColumnField(SysGenTableDTO genTable, List<String> dictList)
    {
        int i=0;

        for(Iterator iterator = genTable.getColumnList().iterator(); iterator.hasNext();)
        {
            SysGenTableColumn column = (SysGenTableColumn)iterator.next();


            if(!StringUtils.isNotBlank(column.getId().toString()))
            {
                if(StringUtils.isBlank(column.getComments())) {
                    column.setComments(column.getName());
                }
                if(StringUtils.startsWithIgnoreCase(column.getJdbcType(), "CHAR") || StringUtils.startsWithIgnoreCase(column.getJdbcType(), "VARCHAR") || StringUtils.startsWithIgnoreCase(column.getJdbcType(), "NARCHAR")) {
                    column.setJavaType("String");
                } else if(StringUtils.startsWithIgnoreCase(column.getJdbcType(), "BLOB")){
                    column.setJavaType("byte[]");
                }
                else
                if(StringUtils.startsWithIgnoreCase(column.getJdbcType(), "DATETIME") || StringUtils.startsWithIgnoreCase(column.getJdbcType(), "DATE") || StringUtils.startsWithIgnoreCase(column.getJdbcType(), "TIMESTAMP"))
                {
                    column.setJavaType("java.util.Date");
                    column.setShowType("dateselect");
                } else
                if(StringUtils.startsWithIgnoreCase(column.getJdbcType(), "BIGINT")
                        || StringUtils.startsWithIgnoreCase(column.getJdbcType(), "NUMBER")
                        || StringUtils.startsWithIgnoreCase(column.getJdbcType(), "DECIMAL")
                        || StringUtils.startsWithIgnoreCase(column.getJdbcType(), "INT")
                        || StringUtils.startsWithIgnoreCase(column.getJdbcType(), "TINYINT"))
                {
                    String[] ss = StringUtils.split(StringUtils.substringBetween(column.getJdbcType(), "(", ")"), ",");
                    if(ss != null && ss.length == 2 && Integer.parseInt(ss[1]) > 0) {
                        column.setJavaType("Double");
                    } else
                    if(ss != null && ss.length == 1 && Integer.parseInt(ss[0]) <= 10) {
                        column.setJavaType("Integer");
                    } else {
                        column.setJavaType("Long");
                    }
                }
                if(column.getJavaType()==null||"".equals(column.getJavaType())){
                    column.setJavaType("String");
                }
                column.setJavaField(S.toCamelCase(column.getName()));

                column.setPk(genTable.getPkList().contains(column.getName()) ? true : false);

                if(column.isPk()==true && column.getName().toLowerCase().contains("id")){
                    column.setJavaField("id");
                }
                column.setQuery(true);
                if(!StringUtils.equalsIgnoreCase(column.getName(), "id") && !StringUtils.equalsIgnoreCase(column.getName(), "create_by") && !StringUtils.equalsIgnoreCase(column.getName(), "create_date") && !StringUtils.equalsIgnoreCase(column.getName(), "del_flag")) {
                    column.setEdit(true);
                } else {
                    column.setEdit(false);
                }
                if(StringUtils.equalsIgnoreCase(column.getName(), "name") || StringUtils.equalsIgnoreCase(column.getName(), "title") || StringUtils.equalsIgnoreCase(column.getName(), "remarks") || StringUtils.equalsIgnoreCase(column.getName(), "update_date")) {
                    column.setList(true);
                } else {
                    column.setList(false);
                }
                if(StringUtils.equalsIgnoreCase(column.getName(), "name") || StringUtils.equalsIgnoreCase(column.getName(), "title")) {
                    column.setQuery(true);
                } else {
                    column.setQuery(false);
                }
                if(StringUtils.equalsIgnoreCase(column.getName(), "name") || StringUtils.equalsIgnoreCase(column.getName(), "title")) {
                    column.setQueryType("like");
                } else {
                    column.setQueryType("=");
                }

                if(StringUtils.startsWithIgnoreCase(column.getJdbcType(), "DATETIME") || StringUtils.startsWithIgnoreCase(column.getJdbcType(), "DATE") || StringUtils.startsWithIgnoreCase(column.getJdbcType(), "TIMESTAMP")) {
                    column.setQueryType("between");
                }

//                if(StringUtils.startsWithIgnoreCase(column.getName(), "user_id"))
//                {
//                    column.setJavaType(User.class.getName());
//                    column.setJavaField(column.getJavaField().replaceAll("Id", ".id|name"));
//                    column.setShowType("userselect");
//                } else
//                if(StringUtils.startsWithIgnoreCase(column.getName(), "office_id"))
//                {
//                    column.setJavaType(Office.class.getName());
//                    column.setJavaField(column.getJavaField().replaceAll("Id", ".id|name"));
//                    column.setShowType("officeselect");
//                } else
//                if(StringUtils.startsWithIgnoreCase(column.getName(), "area_id"))
//                {
//                    column.setJavaType(Area.class.getName());
//                    column.setJavaField(column.getJavaField().replaceAll("Id", ".id|name"));
//                    column.setShowType("areaselect");
//                } else
//                if(StringUtils.startsWithIgnoreCase(column.getName(), "create_by") || StringUtils.startsWithIgnoreCase(column.getName(), "update_by"))
//                {
//                    column.setJavaType(User.class.getName());
//                    column.setJavaField((new StringBuilder(String.valueOf(column.getJavaField()))).append(".id").toString());
//                    column.setShowType("input");
//                } else
//                if(StringUtils.startsWithIgnoreCase(column.getName(), "create_date") || StringUtils.startsWithIgnoreCase(column.getName(), "update_date")) {
//                    column.setShowType("dateselect");
//                } else
                if(StringUtils.equalsIgnoreCase(column.getName(), "remarks") || StringUtils.equalsIgnoreCase(column.getName(), "content")) {
                    column.setShowType("textarea");
                } else
                if(StringUtils.equalsIgnoreCase(column.getName(), "parent_id"))
                {
                    column.setJavaType("This");
                    column.setJavaField("parent.id|name");
                    column.setShowType("treeselect");
                } else
                if(StringUtils.equalsIgnoreCase(column.getName(), "parent_ids"))
                {
                    column.setShowType("input");
                    column.setQueryType("like");
                } else
                if(StringUtils.equalsIgnoreCase(column.getName(), "del_flag"))
                {
                    column.setShowType("radiobox");
                    column.setDictType("del_flag");
                } else
                {
                    if(column.getShowType()=="" || column.getShowType()==null) {
                        column.setShowType("input");
                    }
                }
                if(column.getName().toLowerCase().contains("remark") || StringUtils.startsWithIgnoreCase(column.getJdbcType(), "TEXT")){
                    column.setShowType("textarea");
                }
                if(genTable.getTableType()!="2" && (column.getName().toLowerCase().contains("remark") || StringUtils.startsWithIgnoreCase(column.getJdbcType(), "TEXT"))){
                    column.setShowType("text");
                    column.setQueryType("like");
                }
                if(column.getName().toLowerCase().contains("picture")){
                    column.setShowType("fileselect");
                }
                if(StringUtils.startsWithIgnoreCase(column.getName(), "is_"))
                {
                    column.setShowType("radiobox");
                    if(dictList.contains("is_not")){
                        column.setDictType("is_not");
                    }
                    if(dictList.contains(column.getName()) || dictList.contains(S.toCapitalizeCamelCase(column.getName()))){
                        column.setDictType(column.getName());
                    }
                }

                if(column.getName().toLowerCase().contains("_type")){
                    column.setShowType("select");
                    if(dictList.contains(column.getName()) || dictList.contains(S.toCapitalizeCamelCase(column.getName()))){
                        column.setDictType(column.getName());
                    }
                }


                if(column.getName().toLowerCase().contains("_state") || "state".equals(column.getName().toLowerCase())){
                    column.setShowType("select");
                    if(dictList.contains(column.getName()) || dictList.contains(S.toCapitalizeCamelCase(column.getName()))){
                        column.setDictType(column.getName());
                    }
                }
                if(column.getName().toLowerCase().contains("name")){
                    column.setQueryType("like");
                }

//                if(column.getIsNotBaseField()){
//                    column.setInsert(true);
//                }

                if(i>0 && i<=8){
                    column.setList(true);
                }
                if(i>0 && i<=13 && !column.getName().toLowerCase().contains("picture")){
                    column.setQuery(true);
                }
                i++;
            }
        }

    }

    /*** 
    * @Description: 获取模板地址
    * @Param: [] 
    * @return: java.lang.String 
    * @Author: linsir
    * @Date: 2022/10/10 11:28
    */
    public static String getTemplatePath()
    {
        try
        {
            File file = (new DefaultResourceLoader()).getResource("").getFile();
            if(file != null) {
                return (new StringBuilder(String.valueOf(file.getAbsolutePath()))).append(File.separator).append(StringUtils.replaceEach(GenUtils.class.getName(), new String[]{
                        (new StringBuilder("util.")).append(GenUtils.class.getSimpleName()).toString(), "."
                }, new String[]{
                        "template", File.separator
                })).toString();
            }
        }
        catch(Exception e)
        {
            log.error("{}", e);
        }
        return "";
    }

    /*** 
    * @Description: 将 xml 转化数据对象
    * @Param: [fileName, clazz] 
    * @return: java.lang.Object 
    * @Author: linsir
    * @Date: 2022/10/8 11:41
    */
    public static Object fileToObject(String fileName,Class clazz)
    {
       try {
           String pathName = (new StringBuilder("/templates/modules/gen/")).append(fileName).toString();
           Resource resource = new ClassPathResource(pathName);
           InputStream is = resource.getInputStream();
           BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
           StringBuilder sb = new StringBuilder();

           do {
               String line = br.readLine();
               if(line == null) {
                   break;
               }
               sb.append(line).append("\r\n");
           }while (true);

           if (is!=null)
           {
               is.close();
           }
           if(br != null) {
               br.close();
           }
           return JaxbMapper.fromXml(sb.toString(), clazz);

       }catch (IOException e)
       {
           log.warn("Error file convert: {}", e.getMessage());
       } catch (JAXBException e) {
           e.printStackTrace();
       }
        return null;
    }

    /*** 
    * @Description: 过去配置文件 
    * @Param: [] 
    * @return: com.linsir.gen.entity.SysGenConfig 
    * @Author: linsir
    * @Date: 2022/10/11 14:31
    */
    public static SysGenConfig getSysGenConfig()
    {
        return (SysGenConfig)fileToObject("config.xml", SysGenConfig.class);
    }

    public static List getTemplateList(SysGenConfig sysGenConfig, String category, boolean isChildTable)
    {
        List templateList = Lists.newArrayList();
        if(sysGenConfig != null && sysGenConfig.getCategoryList() != null && category != null)
        {
            for(Iterator iterator = sysGenConfig.getCategoryList().iterator(); iterator.hasNext();)
            {
                SysGenCategory e = (SysGenCategory)iterator.next();
                if(category.equals(e.getValue()))
                {
                    List list = null;
                    if(!isChildTable) {
                        list = e.getTemplate();
                    } else {
                        list = e.getChildTableTemplate();
                    }
                    if(list != null)
                    {
                        for(Iterator iterator1 = list.iterator(); iterator1.hasNext();)
                        {
                            String s = (String)iterator1.next();
                            if(StringUtils.startsWith(s, SysGenCategory.CATEGORY_REF))
                            {
                                templateList.addAll(getTemplateList(sysGenConfig, StringUtils.replace(s, SysGenCategory.CATEGORY_REF, ""), false));
                            } else
                            {
                                SysGenTemplate template = (SysGenTemplate)fileToObject(s, SysGenTemplate.class);
                                if(template != null) {
                                    templateList.add(template);
                                }
                            }
                        }

                    }
                    break;
                }
            }

        }
        return templateList;
    }

    public static Map getDataModel(SysGenScheme genScheme)
    {
        Map model = Maps.newHashMap();
        model.put("packageName", StringUtils.lowerCase(genScheme.getPackageName()));
        model.put("lastPackageName", StringUtils.substringAfterLast((String)model.get("packageName"), "."));
        model.put("moduleName", StringUtils.lowerCase(genScheme.getModuleName()));
        model.put("subModuleName", StringUtils.lowerCase(genScheme.getSubModuleName()));
        model.put("className", StringUtils.uncapitalize(genScheme.getSysGenTable().getClassName()));
        model.put("ClassName", StringUtils.capitalize(genScheme.getSysGenTable().getClassName()));
        model.put("functionName", genScheme.getFunctionName());
        model.put("functionNameSimple", genScheme.getFunctionNameSimple());
       // model.put("functionAuthor", StringUtils.isNotBlank(genScheme.getFunctionAuthor()) ? genScheme.getFunctionAuthor() : UserUtils.getUser().getName());
        //model.put("functionVersion", D.getDate());
        model.put("urlPrefix", (new StringBuilder()).append(model.get("moduleName")).append(StringUtils.isNotBlank(genScheme.getSubModuleName()) ? (new StringBuilder("/")).append(StringUtils.lowerCase(genScheme.getSubModuleName())).toString() : "").append("/").append(model.get("className")).toString());
        model.put("viewPrefix", model.get("urlPrefix"));
        model.put("permissionPrefix", (new StringBuilder()).append(model.get("moduleName")).append(StringUtils.isNotBlank(genScheme.getSubModuleName()) ? (new StringBuilder(":")).append(StringUtils.lowerCase(genScheme.getSubModuleName())).toString() : "").append(":").append(model.get("className")).toString());
        //model.put("dbType", BaseConfig.getConfig("jdbc.type"));
        //model.put("table", genScheme.getGenTable());
        return model;
    }

    public static String generateToFile(SysGenTemplate tpl, Map model, boolean isReplaceFile)
    {
        String fileName = BaseConfig.getProjectPath() + File.separator +

                StringUtils.replaceEach(FreeMarkers.renderString(tpl.getFileName(),new StringBuilder(String.valueOf(tpl.getFilePath())).append("/").toString(), model),
                        new String[] { "//", "/", ".." ,"."}, new String[] { File.separator, File.separator, "__",File.separator }).replace("__", "..")
                +
                FreeMarkers.renderString(tpl.getFileName(),tpl.getFileName(), model);
        log.debug(" fileName === " + fileName);

        String content = FreeMarkers.renderString(tpl.getFileName(),StringUtils.trimToEmpty(tpl.getContent()), model);

        log.debug(" content === \r\n" + content);

        if (isReplaceFile) {
            FileUtils.deleteFile(fileName);
        }
        if (FileUtils.createFile(fileName))
        {
            FileUtils.writeToFile(fileName, content, true);
            log.debug(" file create === " + fileName);
            return "生成成功：" + fileName + "<br/>";
        }
        log.debug(" file extents === " + fileName);
        return "文件已存在：" + fileName + "<br/>";
    }

    /*public static void main(String[] args)
    {
        try
        {
            GenConfig config = getConfig();
            System.out.println(config);
            System.out.println(JaxbMapper.toXml(config));
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }*/
}
